#!/usr/bin/env bash
#-----------------------------------------------------#
# hi ~                                                #
# i'm chen2ha                                         #
# it's my pleasure to use this shell                  #
# u can use this shell to send ssh key to other host  #
# if u have some question or proposal , u can tell me #
# my contact information:                             #
# email: imcxsen@163.com                              #
#-----------------------------------------------------#
# 定义 base_dir 为脚本当前所在路径
base_dir=$(dirname `cd $(dirname $0); pwd`)
ssh_path="$HOME/.ssh"
ssh_list="${base_dir}/bin/ssh_list.txt"

source ${base_dir}/bin/print_log.sh
source ${base_dir}/bin/var_list.sh

# 免密前的检查工作
function check_file () {
  # 判断 ssh_list 文件是否存在，不存在则推出脚本
  ## 存在则定义 ssh_user ssh_host 和 ssh_pass
  ## 和ssh_list 文件内的格式有关，格式为：
  ## <用户名> <主机ip> <用户密码>
  if [[ ! -f "${ssh_list}" ]];then
    error_log "could not find ${ssh_list}, please check it ~"
    exit 255
  else
    ssh_user=($(awk '$1 != "#" {print $1}' ${ssh_list}))
    ssh_host=($(awk '$1 != "#" {print $2}' ${ssh_list}))
    ssh_pass=($(awk '$1 != "#" {print $3}' ${ssh_list}))
  fi
  
  # 判断 ssh_user 和 ssh_host 的变量值数量是否一致
  ## 不一致则推出脚本
  if [[ "${#ssh_user[@]}" != "${#ssh_host[@]}" ]];then
    error_log "please check formart: ${ssh_list} ~"
    exit 255
  fi
  
  # 判断 ssh_user 和 ssh_pass 的变量值数量是否一致
  ## 不一致则推出脚本
  if [[ "${#ssh_user[@]}" != "${#ssh_pass[@]}" ]];then
    error_log "please check formart: ${ssh_list} ~"
    exit 255
  fi
  
  # 检查本机是否有 expect 命令
  ## 免密依赖 expect 完成面交互的操作
  ## 输出提示信息，告知如何安装 expect
  ## 目前常用发行版 redhat/centos/fedora/suse/debian/ubuntu
  ## 其他发行版如：麒麟、UOS等国产 linux 暂时未涉及，需要自行了解
  which expect &> /dev/null
  if [[ "$?" -ne "0" ]];then
    error_log "expect is not found, we need it ~"
    info_log "u can use 'yum install -y expect' to install it, if your system is redhat/centos/fedora"
    info_log "u can use 'zypper install -y expect' to install it, if your system is suse"
    info_log "u can use 'apt-get install -y expect' to install it, if your system is debian/ubuntu"
    exit 1
  fi
  
  # log_file 文件存在则清空文件内容
  [[ ! -f "${log_file}" ]] || > ${log_file}
}

# 开始免密
function send_ssh_key () {
  # 判断 ssh_path 目录下是否有 id_rsa.pub 文件
  ## 此脚本免密使用的是 rsa 加密算法
  ## 如果 id_rsa.pub 文件不存在，则通过 ssh-keygen 来生成 rsa 算法的 ssh 证书
  if [[ ! -f "${ssh_path}/id_rsa.pub" ]];then
    ssh-keygen -t rsa -P "" -f ${ssh_path}/id_rsa -q
  fi
  
  for (( u=0; u<${#ssh_host[@]}; u++ ))
  do
    info_log "sending key to ${ssh_host[u]} now ~"
    # 通过 expect 分发 id_rsa.pub 公钥到其他节点来完成免密操作
    expect -c "
    spawn ssh-copy-id ${ssh_options} -i ${ssh_path}/id_rsa.pub ${ssh_user[u]}@${ssh_host[u]}
      expect {
        \"*es/no*\" {send \"yes\r\"; exp_continue}
        \"*assword*\" {send \"${ssh_pass[u]}\r\"; exp_continue}
        \"*assword*\" {send \"${ssh_pass[u]}\r\";}
             }"
    # 判断 expect 命令返回的状态码是否为 0
    ## 为 0 则输出 success
    ## 不为 0 则输出 failed ， 并退出脚本
    if [[ "$?" -ne "0" ]];then
      error_log "send key to ${ssh_host[u]} failed"
      exit 111
    else
      success_log "send key to ${ssh_host[u]} success"
    fi
  done
  
  # 上个循环完成，返回状态码为 0 后，验证免密效果
  if [[ "$?" -eq "0" ]];then
    for (( t=0; t<${#ssh_host[@]}; t++ ))
    do
      ssh ${ssh_user[t]}@${ssh_host[t]} "date"
    done
    info_log "have fun"
  fi
}

check_file
send_ssh_key
